package com.yt.order.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.yt.common.enums.CodeEnum;
import com.yt.common.exception.BusinessException;
import com.yt.order.common.config.YmlConfig;
import com.yt.order.models.bo.*;
import com.yt.order.models.dto.WorkOrderInfoDTO;
import com.yt.order.models.service.IWorkOrderInfoService;
import com.yt.order.mapper.WorkOrderInfoMapper;
import com.yt.order.models.vo.EmployeeCommissionStatVO;
import com.yt.order.models.vo.WorkOrderInfoVO;
import com.yt.order.models.vo.WorkOrderStatisticVO;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 工单信息服务实现类
 *
 * @author chen
 * @Date 2025-09-05 18:26:57
 */
@DubboService
@Service
public class WorkOrderInfoServiceImpl extends com.baomidou.mybatisplus.service.impl.ServiceImpl<WorkOrderInfoMapper, WorkOrderInfoDTO> implements IWorkOrderInfoService {

    @Resource
    private YmlConfig ymlConfig;

    @Resource
    private WorkOrderInfoMapper workOrderInfoMapper;

    @Override
    public boolean add(WorkOrderInfoSaveBO saveBO) {
        // 1. 参数校验
        validateWorkOrderSaveBO(saveBO);

        // 2. BO转换为DTO
        WorkOrderInfoDTO dto = new WorkOrderInfoDTO();
        BeanUtils.copyProperties(saveBO, dto);

        // 3. 设置默认值（新增提成计算）
        setWorkOrderDefaultValues(dto);

        // 4. 自动计算提成（经费的30%）
        dto.setCommission(dto.getMoney() * 0.3f);

        // 5. 生成并设置主键ID
        Long id = ymlConfig.getPkId();
        dto.setId(id);

        // 6. 插入数据库
        return this.insert(dto);
    }

    /**
     * 工单信息参数校验
     */
    private void validateWorkOrderSaveBO(WorkOrderInfoSaveBO saveBO) {
        if (saveBO == null) {
            throw new BusinessException(CodeEnum.FAIL_100001.getCode(), "工单信息不能为空");
        }
        if (saveBO.getTitle() == null || saveBO.getTitle().trim().isEmpty()) {
            throw new BusinessException(CodeEnum.FAIL_100002.getCode(), "工单标题不能为空");
        }
        if (saveBO.getName() == null || saveBO.getName().trim().isEmpty()) {
            throw new BusinessException(CodeEnum.FAIL_100002.getCode(), "联系人姓名不能为空");
        }
        if (saveBO.getPhone() == null || saveBO.getPhone().trim().isEmpty()) {
            throw new BusinessException(CodeEnum.FAIL_100002.getCode(), "联系人电话不能为空");
        }
        if (saveBO.getType() == null || (saveBO.getType() != 0 && saveBO.getType() != 1)) {
            throw new BusinessException(CodeEnum.FAIL_100003.getCode(), "工单类型必须为0（客户下单）或1（系统自建）");
        }
        if (saveBO.getStatus() != null && (saveBO.getStatus() < 0 || saveBO.getStatus() > 3)) {
            throw new BusinessException(CodeEnum.FAIL_100003.getCode(), "工单状态必须为0-3之间的整数");
        }

        if (saveBO.getMoney() == null || saveBO.getMoney() <= 0) {
            throw new BusinessException(CodeEnum.FAIL_100002.getCode(), "工单经费不能为空且必须大于0");
        }
    }

    /**
     * 设置工单信息默认值
     */
    private void setWorkOrderDefaultValues(WorkOrderInfoDTO dto) {
        Date now = new Date();

        // 乐观锁版本号默认0
        dto.setRevision(dto.getRevision() != null ? dto.getRevision() : 0);

        // 状态默认0-未派单（如果未指定）
        dto.setStatus(dto.getStatus() != null ? dto.getStatus() : 0);

        // 支付状态默认0-未支付（如果未指定）
        dto.setPayStatus(dto.getPayStatus() != null ? dto.getPayStatus() : 0);

        // 地址、图片等非必填项默认空字符串（避免null）
        dto.setAddress(dto.getAddress() != null ? dto.getAddress() : "");
        dto.setPic(dto.getPic() != null ? dto.getPic() : "");
        dto.setDes(dto.getDes() != null ? dto.getDes() : "");

        // 创建时间和更新时间默认当前时间
        dto.setCreateTime(dto.getCreateTime() != null ? dto.getCreateTime() : now);
        dto.setUpdateTime(dto.getUpdateTime() != null ? dto.getUpdateTime() : now);
    }

    @Override
    public WorkOrderInfoVO selectVoById(Long id) {
        return baseMapper.selectVoById(id);
    }

    @Override
    public Page<WorkOrderInfoVO> selectPageVo(Page<WorkOrderInfoVO> page, WorkOrderInfoBO bo) {
        List<WorkOrderInfoVO> records = workOrderInfoMapper.selectPageVo(page, bo);
        return page.setRecords(records);
    }

    @Override
    public List<WorkOrderInfoVO> selectVoByTitle(String title) {
        return baseMapper.selectVoByTitle(title);
    }


    @Override
    public WorkOrderStatisticVO statistic(WorkOrderStatisticBO bo) {
        // 1. 参数校验
        validateStatisticBO(bo);

        WorkOrderStatisticVO result = new WorkOrderStatisticVO();
        EntityWrapper<WorkOrderInfoDTO> wrapper = buildStatisticWrapper(bo);

        // 2. 统计总数量
        Long totalCount = baseMapper.selectCount(wrapper).longValue();
        result.setTotalCount(totalCount);

        // 3. 状态分布统计（确保所有状态都有默认值，避免前端缺失）
        List<Map<String, Object>> statusList = baseMapper.countByStatus(
                bo.getStatus(), bo.getPayStatus(), bo.getType(),
                bo.getStartTime(), bo.getEndTime(), bo.getDispatcherId()
        );
        Map<Integer, Long> statusMap = new HashMap<>();
        // 初始化所有可能的状态（0-3）
        for (int i = 0; i <= 3; i++) {
            statusMap.put(i, 0L);
        }
        // 填充查询结果
        for (Map<String, Object> map : statusList) {
            Integer status = (Integer) map.get("status");
            Long count = ((Number) map.get("count")).longValue();
            if (status == 4) {
                statusMap.put(2, statusMap.get(2) + count);
            } else {
                statusMap.put(status, count);
            }
        }
        result.setStatusDistribution(statusMap);

        // 4. 时间趋势统计（按天分组，确保时间连续）
        List<Map<String, Object>> timeList = baseMapper.countByTime(
                bo.getStatus(), bo.getPayStatus(), bo.getType(),
                bo.getStartTime(), bo.getEndTime(), bo.getDispatcherId()
        );
        Map<String, Long> timeMap = new TreeMap<>(); // 按时间排序
        // 填充查询结果
        for (Map<String, Object> map : timeList) {
            String timeKey = (String) map.get("timeKey");
            Long count = ((Number) map.get("count")).longValue();
            timeMap.put(timeKey, count);
        }
        result.setTimeTrend(timeMap);

        // 5. 类型分布统计（确保所有类型都有默认值）
        List<Map<String, Object>> typeList = baseMapper.countByType(
                bo.getStatus(), bo.getPayStatus(),
                bo.getStartTime(), bo.getEndTime(), bo.getDispatcherId()
        );
        Map<Integer, Long> typeMap = new HashMap<>();
        // 初始化所有可能的类型（0-1）
        typeMap.put(0, 0L);
        typeMap.put(1, 0L);
        // 填充查询结果
        for (Map<String, Object> map : typeList) {
            Integer type = (Integer) map.get("type");
            Long count = ((Number) map.get("count")).longValue();
            typeMap.put(type, count);
        }
        result.setTypeDistribution(typeMap);

        // 6. 完成率计算（处理除零和状态定义）
        if (totalCount > 0) {
            long completedCount = statusMap.getOrDefault(2, 0L)+ statusMap.getOrDefault(4, 0L); // 状态2为已完成
            result.setCompletionRate(completedCount * 1.0 / totalCount);
        } else {
            result.setCompletionRate(0.0);
        }

        return result;
    }

    /**
     * 统计参数校验
     */
    private void validateStatisticBO(WorkOrderStatisticBO bo) {
        if (bo == null) {
            throw new BusinessException(CodeEnum.FAIL_100001.getCode(), "统计参数不能为空");
        }
        // 时间范围校验
        if (bo.getStartTime() != null && bo.getEndTime() != null
                && bo.getStartTime().after(bo.getEndTime())) {
            throw new BusinessException(CodeEnum.FAIL_100003.getCode(), "开始时间不能晚于结束时间");
        }
        // 状态范围校验
        if (bo.getStatus() != null && (bo.getStatus() < 0 || bo.getStatus() > 3)) {
            throw new BusinessException(CodeEnum.FAIL_100003.getCode(), "状态值必须为0-3");
        }
        // 类型范围校验
        if (bo.getType() != null && (bo.getType() < 0 || bo.getType() > 1)) {
            throw new BusinessException(CodeEnum.FAIL_100003.getCode(), "类型值必须为0或1");
        }
        // 支付状态范围校验
        if (bo.getPayStatus() != null && (bo.getPayStatus() < 0 || bo.getPayStatus() > 3)) {
            throw new BusinessException(CodeEnum.FAIL_100003.getCode(), "支付状态值必须为0-3");
        }
    }

    /**
     * 构建统计查询条件
     */
    private EntityWrapper<WorkOrderInfoDTO> buildStatisticWrapper(WorkOrderStatisticBO bo) {
        EntityWrapper<WorkOrderInfoDTO> wrapper = new EntityWrapper<>();
        if (bo.getStatus() != null) wrapper.eq("status", bo.getStatus());
        if (bo.getPayStatus() != null) wrapper.eq("pay_status", bo.getPayStatus());
        if (bo.getType() != null) wrapper.eq("type", bo.getType());
        if (bo.getStartTime() != null) wrapper.ge("create_time", bo.getStartTime());
        if (bo.getEndTime() != null) wrapper.le("create_time", bo.getEndTime());
        if (bo.getDispatcherId() != null) wrapper.eq("dispatcher_id", bo.getDispatcherId());
        return wrapper;
    }
    @Override
    public List<WorkOrderInfoVO> filterWorkOrders(WorkOrderFilterBO bo) {
        return baseMapper.selectByFilter(bo);
    }

    @Override
    public Page<WorkOrderInfoVO> selectPageVoByTitle(Page<WorkOrderInfoVO> page, String title) {
        List<WorkOrderInfoVO> records = workOrderInfoMapper.selectPageVoByTitle(page, title);
        return page.setRecords(records);
    }

    @Override
    public boolean dispatch(WorkOrderDispatchBO dispatchBO) {
        // 参数校验
        if (dispatchBO == null || dispatchBO.getWorkOrderId() == null || dispatchBO.getEmployeeId() == null) {
            throw new BusinessException(CodeEnum.FAIL_100002.getCode(), "工单ID和接单员ID不能为空");
        }

        // 查询工单是否存在且为未派单状态
        WorkOrderInfoDTO dto = this.selectById(dispatchBO.getWorkOrderId());
        if (dto == null) {
            throw new BusinessException(CodeEnum.FAIL_100010.getCode(), "工单不存在");
        }
        if (dto.getStatus() != 0) {
            throw new BusinessException(CodeEnum.FAIL_100012.getCode(), "只有未派单状态的工单可以进行派单操作");
        }

        // 更新工单信息
        dto.setEmployeeId(dispatchBO.getEmployeeId());
        dto.setStatus(1); // 状态改为进行中
        dto.setUpdateTime(new Date());

        return this.updateById(dto);
    }

    @Override
    public Page<WorkOrderInfoVO> selectUnassignedPage(Page<WorkOrderInfoVO> page, WorkOrderInfoBO bo) {
        // 查询未派单状态的工单
        if (bo == null) {
            bo = new WorkOrderInfoBO();
        }
        bo.setStatus(0);

        List<WorkOrderInfoVO> records = workOrderInfoMapper.selectPageVo(page, bo);
        return page.setRecords(records);
    }

    @Override
    public EmployeeCommissionStatVO statEmployeeCommission(Long employeeId, Date startTime, Date endTime) {
        if (employeeId == null || startTime == null || endTime == null) {
            throw new BusinessException(CodeEnum.FAIL_100002.getCode(), "接单员ID和时间范围不能为空");
        }
        return workOrderInfoMapper.statEmployeeCommission(employeeId, startTime, endTime);
    }

    @Override
    public boolean archiveCompletedOrders() {
        int rows = workOrderInfoMapper.archiveCompletedOrders();
        return rows > 0;
    }
}